//  Inside Microsoft Exchange 2007 Web Services
//  Chapter 6
//
//  Copyright (c) 2007 David Sterling, Ben Spain, Mark Taylor, Huw Upshall, Michael Mainer.
//  All rights reserved.
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;
using ProxyHelpers.EWS;

namespace ResolveAndExpand
{
    class Program
    {
        static void Main(string[] args)
        {
            ExchangeServiceBinding binding = new ExchangeServiceBinding();
            binding.Url = @"https://yourServer/ews/Exchange.asmx";
            binding.Credentials = new NetworkCredential(
                "username",
                "password",
                "domain");

            // Pass in a partial name.  If it matches a DL, then it
            // will expand that DL as well.
            //
            ResolveAndExpand(
                    binding,
                    "mako");
        }

        /// <summary>
        /// Resolves the passed partialName and prints out contacts and expands 
        /// DLs (Listing 6-28)
        /// </summary>
        /// <param name="binding">Binding to use for calls</param>
        /// <param name="partialName">Ambiguous name to match</param>
        /// 
        public static void ResolveAndExpand(
                             ExchangeServiceBinding binding,
                             string partialName)
        {
            ResolveNamesType resolveRequest = new ResolveNamesType();
            resolveRequest.ReturnFullContactData = false;
            resolveRequest.UnresolvedEntry = partialName;
            ResolveNamesResponseType resolveResponse =
                        binding.ResolveNames(resolveRequest);

            ResolveNamesResponseMessageType resolveMessage =
                    resolveResponse.ResponseMessages.Items[0] as
                              ResolveNamesResponseMessageType;
            int offset = 0;

            // For each match we either write out the contact or expand the dl
            //
            foreach (ResolutionType singleMatch in
                          resolveMessage.ResolutionSet.Resolution)
            {
                // Always write out the info (contact or DL)
                //
                WriteOutMailbox(offset, singleMatch.Mailbox);
                if ((singleMatch.Mailbox.MailboxType == MailboxTypeType.PrivateDL) ||
                    (singleMatch.Mailbox.MailboxType == MailboxTypeType.PublicDL))
                {
                    // It's a DL, so expand it
                    //
                    ExpandDL(binding, offset, singleMatch.Mailbox);
                }
            }
        }

        /// <summary>
        /// Expands the passed DL and writes out its membership
        /// </summary>
        /// <param name="binding">Binding to use for the call</param>
        /// <param name="offset">Offset number of tabs for printing</param>
        /// <param name="dlToExpand">Mailbox for DL to expand</param>
        /// 
        private static void ExpandDL(
                       ExchangeServiceBinding binding,
                       int offset,
                       EmailAddressType dlToExpand)
        {
            // increment the offset so we show nesting when we print out the 
            // results.
            //
            offset++;
            ExpandDLType expandRequest = new ExpandDLType();
            expandRequest.Mailbox = dlToExpand;
            ExpandDLResponseType expandResponse = binding.ExpandDL(expandRequest);

            ExpandDLResponseMessageType expandMessage =
                       expandResponse.ResponseMessages.Items[0] as
                                 ExpandDLResponseMessageType;

            // If there are no mail-enable contacts in the DL, the DL expansion will 
            // come back empty so check for null.  Yes, that did bite me.
            //
            if (expandMessage.DLExpansion.Mailbox != null)
            {
                foreach (EmailAddressType mailbox in
                                expandMessage.DLExpansion.Mailbox)
                {
                    WriteOutMailbox(offset, mailbox);
                    if ((mailbox.MailboxType == MailboxTypeType.PrivateDL) ||
                        (mailbox.MailboxType == MailboxTypeType.PublicDL))
                    {
                        // recursive expansion of DLs
                        //
                        ExpandDL(binding, offset, mailbox);
                    }
                }
            }
        }

        /// <summary>
        /// Writes the mailbox info out to the console
        /// </summary>
        /// <param name="offset">offset to use for tabbing</param>
        /// <param name="mailbox">Mailbox to write out</param>
        /// 
        private static void WriteOutMailbox(int offset, EmailAddressType mailbox)
        {
            StringBuilder sb = new StringBuilder();
            for (int pad = 0; pad < offset; pad++)
            {
                sb.Append("\t");
            }
            string padding = sb.ToString();
            Console.WriteLine(
                   "{0}Name: {1}\r\n{2}Email: {3}\r\n{4}Type:{5}\r\n" +
                   "{6}RoutingType:{7}\r\n{8}ItemId:{9}\r\n--------------------",
                   padding,
                   mailbox.Name == null ? "<NULL>" : mailbox.Name,
                   padding,
                   mailbox.EmailAddress == null ? "<NULL>" : mailbox.EmailAddress,
                   padding,
                   mailbox.MailboxType.ToString(),
                   padding,
                   mailbox.RoutingType == null ? "<NULL>" : mailbox.RoutingType,
                   padding,
                   mailbox.ItemId == null ? "<NULL>" : mailbox.ItemId.Id);
        }
    }
}
